home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CU Amiga Super CD-ROM 16
/
CU Amiga Magazine's Super CD-ROM 16 (1997-10-16)(EMAP Images)(GB)[!][issue 1997-11].iso
/
CUCD
/
Online
/
HBBS
/
Source
/
Node
/
Node_Serial.c
< prev
next >
Wrap
C/C++ Source or Header
|
1997-08-28
|
13KB
|
535 lines
#include <string.h>
#include <math.h>
#include <stdio.h>
#include <exec/types.h>
#include <libraries/locale.h>
#include <exec/memory.h>
#include <dos/dosextens.h>
#include <intuition/screens.h>
#include <intuition/intuition.h>
#include <intuition/gadgetclass.h>
#include <libraries/gadtools.h>
#include <diskfont/diskfont.h>
#include <utility/utility.h>
#include <graphics/gfxbase.h>
#include <devices/console.h>
#include <workbench/workbench.h>
#include <graphics/scale.h>
#include <clib/locale_protos.h>
#include <clib/exec_protos.h>
#include <clib/wb_protos.h>
#include <clib/intuition_protos.h>
#include <clib/gadtools_protos.h>
#include <clib/graphics_protos.h>
#include <clib/utility_protos.h>
#include <clib/diskfont_protos.h>
#include <dos/dos.h>
#include <dos/dostags.h>
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <time.h>
#include <libraries/reqtools.h>
#include <clib/alib_protos.h>
#include <clib/dos_protos.h>
#include <clib/reqtools_protos.h>
#include "NodeGUI.h"
#include <devices/serial.h>
#include <hardware/cia.h>
#include <clib/exec_protos.h>
#include <clib/alib_protos.h>
#include "NodeGUI.h"
#define NOTMAIN
#define ClrSignal(s) SetSignal(0,s)
#include <hbbs/types.h>
#include <hbbs/defines.h>
#include <hbbs/structures.h>
#include <hbbs/strings.h>
#include <hbbs/errors.h>
#include <hbbs/shared_protos.h>
#include <hbbs/Files.h>
#include "Node_Input_protos.h"
//#include "Node_Console_protos.h"
#include <HBBS/Hbbscommon_protos.h>
#ifdef __SASC
#include <HBBS/hbbscommon_pragmas_sas.h>
#else
#include <HBBS/hbbscommon_pragmas_stc.h>
#endif
#include <HBBS/Hbbsnode_protos.h>
#ifdef __SASC
#include <HBBS/Hbbsnode_pragmas_sas.h>
#else
#include <HBBS/Hbbsnode_pragmas_stc.h>
#endif
extern struct NodeData *N_ND;
extern struct BBSGlobalData *BBSGlobal;
extern struct Library *HBBSCommonBase;
extern struct Library *HBBSNodeBase;
char errstr[2048]; // big enough ?
char LastChar=0;
void SerReset( void )
{
// this routine reads in all waiting data from the serial port and then dumps it!
UBYTE *mem;
ULONG bytes;
if (bytes=SerQueryData())
{
if (mem=AllocVec(bytes,MEMF_PUBLIC))
{
WaitSerReadBlock(mem,bytes); // *C* ooh naughty.. should really have somekind of wait() here..
// if (N_ND->ConOK)
// {
// ConWriteStr("Serial Port had this data in it's buffer:\r\n");
// ConWriteData(mem,bytes);
// ConWriteStr("End Dump\r\n");
// }
FreeVec(mem);
}
}
}
void CleanupSerial( void )
{
if (!N_ND->NodeDevice.SysopNode)
{
if (N_ND->SerBuffer)
{
if (N_ND->SerPort)
{
if (N_ND->SerWrite)
{
if (N_ND->SerOPEN)
{
if (N_ND->SerRead)
{
SerReset();
AbortSerRead(); // will only abort id request submitted..
FreeVec(N_ND->SerRead);
}
CloseDevice((struct IORequest*)N_ND->SerWrite);
N_ND->SerOPEN=FALSE;
}
DeleteExtIO((struct IORequest*)N_ND->SerWrite);
}
DeletePort(N_ND->SerPort);
}
FreeVec(N_ND->SerBuffer);
}
}
N_ND->SerOK=FALSE;
}
V_BOOL OpenSerial( void )
{
N_ND->SerWaiting=FALSE;
N_ND->SerOK=FALSE;
N_ND->SerOPEN=FALSE;
if (!N_ND->NodeDevice.SysopNode)
{
if (N_ND->SerBuffer=AllocVec(DEF_SERBUFLEN,MEMF_PUBLIC))
{
N_ND->SerBufferLen=DEF_SERBUFLEN;
if (N_ND->SerPort=CreatePort(0,0))
{
if (N_ND->SerWrite = (struct IOExtSer *) CreateExtIO(N_ND->SerPort,(ULONG)sizeof(struct IOExtSer)))
{
N_ND->SerWrite->io_SerFlags = SERF_7WIRE;
if (!(OpenDevice((STRPTR)N_ND->NodeDevice.SerialDevice,(ULONG)N_ND->NodeDevice.SerialUnit,(struct IORequest *)N_ND->SerWrite,0L) ))
{
// N_ND->SerWrite->io_SerFlags &= ~SERF_XDISABLED; // ENABLE XON/XOFF
// N_ND->SerWrite->io_RBufLen=8192;
// note: hydracom wasworking with rbuf left at defualt with 8n1.device on a1200 with serial port in 7wire & shared mode
N_ND->SerWrite->io_Baud = N_ND->NodeDevice.SerialBaud;
N_ND->SerWrite->IOSer.io_Command = SDCMD_SETPARAMS;
DoIO((struct IORequest *)N_ND->SerWrite);
N_ND->SerOPEN=TRUE;
if (N_ND->SerRead = (struct IOExtSer*)AllocVec(sizeof(struct IOExtSer),MEMF_PUBLIC) )
{
// duplicate data...
memcpy(N_ND->SerRead,N_ND->SerWrite,sizeof(struct IOExtSer));
SerReset();
N_ND->SerOK=TRUE;
return(TRUE);
}
}
else HBBS_DoErrorMessage(EMSG_NODEVICE,N_ND->NodeNum,NULL);
}
}
}
CleanupSerial();
}
return(FALSE);
}
ULONG ModemGetLine( void )
{
ULONG ReturnedSigs;
UBYTE CurrentChar[2]={0,0}; // 2 chars, use ¤tchar for null terminated string type..
ULONG retval=IN_NOTHING; // this must NOT be returned to the caller!!!!!
struct TimerData *TD;
N_ND->CurrentLine[0]=0; // null terminate the string..
if (TD=SubmitTimer(N_ND->NodeTimer,N_ND->NodeDevice.MaxCommandWait,0))
{
do
{
if (!N_ND->SerWaiting)
{
SendSerReadData();
}
N_ND->SerSig=DEF_SERSIG;
N_ND->TimerSig=DEF_TIMERSIG;
// we cant use SetupSigs() and WaitAllSigs() because if we are resetting
// the modem after a LOGIN_LOCAL sersigs is set to 0... :-)
ReturnedSigs=Wait(N_ND->SerSig | N_ND->TimerSig);
while (HandleSerSigs(ReturnedSigs) && retval==IN_NOTHING)
{
// if DumpModem is enabled then write out every single char that we get when talking to
// the modem.
if (N_ND->NodeDevice.DumpModem)
{
printf("%d \"",N_ND->IBuffer[0]);
if (N_ND->IBuffer[0]>=0x20 && N_ND->IBuffer[0]!=127) printf("%c",N_ND->IBuffer[0]);
printf("\" ");
}
// ok, we got some data from somehwere...
CurrentChar[0]=N_ND->IBuffer[0];
if (CurrentChar[0]>=0x20 && CurrentChar[0]!=127) // i.e. not unprintable or a control char..
{
strcat(N_ND->CurrentLine,CurrentChar);
}
else
{
if (CurrentChar[0]=='\r' && LastChar!='\n' && LastChar !='\r')
{
if (strlen(N_ND->CurrentLine)>0) retval=IN_GOTLINE;
}
if (CurrentChar[0]=='\n' && LastChar!='\n' && LastChar !='\r')
{
if (strlen(N_ND->CurrentLine)>0) retval=IN_GOTLINE;
}
}
LastChar=N_ND->IBuffer[0];
}
if ((retval==IN_NOTHING) && (CheckTimer(N_ND->NodeTimer,TD)))
{
TD=NULL;
retval=IN_TIMEOUT;
}
}
while (retval==IN_NOTHING);
if (TD) AbortTimer(N_ND->NodeTimer,TD);
if (N_ND->NodeDevice.ModemDebug && N_ND->ConOK)
{
ConWriteStr(N_ND->CurrentLine);
ConWriteStr(str_CRLF);
}
if (N_ND->SerWaiting) AbortSerRead();
}
if (N_ND->NodeDevice.DumpModem)
{
printf("'%s' \n",N_ND->CurrentLine);
}
return(retval);
}
void ModemError(char *command, char *result)
{
if (N_ND->NodeDevice.ModemLog)
{
sprintf(errstr,"When Sending the command \"%s\" the modem returned \"%s\"",command,result);
HBBS_LogError(N_ND->NodeSettings.ModemLogFile,ERR_GENERAL,errstr,TYPE_WARNING);
}
HBBS_LogError(N_ND->NodeSettings.NodeLogFile,ERR_GENERAL,"Modem Error!",TYPE_WARNING);
}
void TurnEchoOn( void )
{
struct Node *node;
short retriesleft;
BOOL Done;
ULONG result;
PutText("\033[37;0m\n");
for (node=N_ND->NodeDevice.TurnOnEcho->lh_Head;node->ln_Succ;node=node->ln_Succ)
{
if (node->ln_Name)
{
Done=FALSE;
retriesleft=N_ND->NodeDevice.EchoRetries;
do
{
if (retriesleft!=N_ND->NodeDevice.EchoRetries)
{
ConWriteStr("Retrying Modem...\n\r");
}
retriesleft--;
Delay(N_ND->NodeDevice.TurnOnEchoDelay);
SerReset();
SerWriteStr(node->ln_Name);
SerWriteStr("\r");
if (N_ND->NodeDevice.UseCRLF)
{
SerWriteStr("\n");
}
if (result=ModemGetLine()==IN_GOTLINE)
{
// ok, got some input..
if (stricmp(node->ln_Name,N_ND->CurrentLine)==0)
{ // echo is already on, so discard this line and read another line..
result=ModemGetLine();
}
if (result==IN_GOTLINE)
{
if (stricmp("OK",N_ND->CurrentLine)==0) Done=TRUE;
}
}
} while (!Done && retriesleft>0);
}
}
SerReset();
}
V_BOOL SendModemString(char *str)
{
ULONG err=1;
ULONG loop,loop2;
BOOL linemismatch;
char *cvtstr;
if (cvtstr=DupStr(str))
{
// remove the '~'s fromt the string so that we can compare the returned string from the modem
// (the modem won't return the '~'s because it'll never get them!
loop=0,loop2=0;
while (str[loop])
{
if (str[loop]!='~')
{
cvtstr[loop2]=str[loop];
}
loop2++;
loop++;
}
cvtstr[loop2]=0;
loop2=N_ND->NodeDevice.CommandRetries;
do
{
// this loop sends the command to the modem and wait for the characters to
// be echoed back. if we don't get back what we send we try it again!
loop=N_ND->NodeDevice.CommandRetries;
do
{
Delay(N_ND->NodeDevice.DelayBetweenCmds);
SerReset(); //clear all crap before we send our new string..
SerDelayWriteStr(str); // send the command to the modem
SerWriteStr("\r");
if (N_ND->NodeDevice.UseCRLF)
{
SerWriteStr("\n");
}
ModemGetLine(); // then check the modem echo'd the chars we sent it.
if (linemismatch=(stricmp(cvtstr,N_ND->CurrentLine)!=0 ? TRUE : FALSE)) // compare with cvtstr and not str..
{
// modem did not retunr the same string we sent it, the modem's local echo must be off so turn it on
TurnEchoOn();
}
} while (loop-- && linemismatch); // if we had a line mismatch then retry sending the command now that echo is on.
// now wait the modem's responce from the command we sent it.
// right if we are here then we know we're gonna get a blank line and a timeout
// or OK OR ERROR.. if we don't get OK then we retry the command...
ModemGetLine();
} while (loop2-- && stricmp(N_ND->CurrentLine,"OK")!=0 && (err=stricmp(N_ND->CurrentLine,"ERROR"))==0);
if (!err) ModemError(str,N_ND->CurrentLine);
FreeStr(cvtstr);
}
return(err);
}
void OffHook( void )
{
if (N_ND->NodeSettings.UseDevice)
{
SendModemString(N_ND->NodeDevice.OffHookString);
}
}
void ReOpenSerial( void )
{
// closing and opening the serial port has the effect of dropping dtr,
// forcing a hangup of the modem.
V_SMALLNUM loop=N_ND->NodeDevice.ReOpenRetries;
if (!N_ND->NodeDevice.SysopNode)
{
CleanupSerial();
while (loop-- && N_ND->SerOK==FALSE)
{
Delay(N_ND->NodeDevice.ReOpenDelay);
OpenSerial();
}
if (!N_ND->SerOK)
{
HBBS_LogError(BBSGlobal->ErrorLogFile,ERR_GENERAL,ESTR_NOSERIAL,TYPE_CRITICAL);
}
}
}
void SendHangupCommands( void )
{
struct Node *node;
for (node=N_ND->NodeDevice.CommandModeString->lh_Head;node->ln_Succ;node=node->ln_Succ)
{
if (node->ln_Name) SerDelayWriteStr(node->ln_Name);
}
SendModemString(N_ND->NodeDevice.HangUpString);
}
void HangUp( void )
{
if (N_ND->NodeSettings.UseDevice)
{
if (!N_ND->NodeDevice.NullModemCable)
{
if (N_ND->NodeDevice.DropDTRHangup)
{
ReOpenSerial();
}
else
{
SendHangupCommands();
}
if (CarrierLost())
{
if (N_ND->ConOK) ConWriteStr("Hungup OK.\r\n");
}
else
{
if (N_ND->NodeDevice.DropDTRHangup)
{
sprintf(errstr,"Could not hangup using DTR.");
HBBS_LogError(N_ND->NodeSettings.NodeLogFile,ERR_GENERAL,errstr,TYPE_WARNING);
SendHangupCommands();
}
else
{
sprintf(errstr,"Could not hangup using commands, trying DTR.");
HBBS_LogError(N_ND->NodeSettings.NodeLogFile,ERR_GENERAL,errstr,TYPE_WARNING);
ReOpenSerial();
}
if (!CarrierLost())
{
sprintf(errstr,"Could not hangup using hangup commands either.");
HBBS_LogError(N_ND->NodeSettings.NodeLogFile,ERR_GENERAL,errstr,TYPE_WARNING);
}
}
OffHook();
}
else
{
ReOpenSerial();
}
}
}
V_BOOL InitModem( void )
{
struct Node *node;
if (N_ND->NodeSettings.UseDevice)
{
if (N_ND->NodeDevice.ModemDebug && N_ND->ConOK)
{
ConWriteStr("Initialising Modem...\n\r");
}
TurnEchoOn();
Delay(N_ND->NodeDevice.DelayBetweenCmds);
for (node=N_ND->NodeDevice.ModemInit->lh_Head;node->ln_Succ;node=node->ln_Succ)
{
if (node->ln_Name) SendModemString(node->ln_Name);
}
// wait a bit nd dump any data.
Delay(N_ND->NodeDevice.DelayBetweenCmds);
SerReset();
if (!N_ND->NodeSettings.Iconified)
{
// set gadget on noe gui window so that it says "ONHOOK"
GT_SetGadgetAttrs(NodeWndGadgets[NodeWnd_OffHook],NodeWnd,NULL,GTCY_Active,0,TAG_DONE);
}
}
return(TRUE);
}